/**
 * 
 */
package info.niwota.frames.net;

import info.niwota.frames.Debug;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;

/**
 * @author qiangli
 * 
 */
public class TransportAdapter implements RequestHandler {

	private static final String TAG = "TransportAdapter";

	private static ExecutorService pool = Executors.newCachedThreadPool();
	
	protected Context ctx;

	public TransportAdapter(Context ctx) {
		this.ctx = ctx;
	}

	public void handle(ObjectInputStream in, ObjectOutputStream out) throws Exception {

		try {
//			TransportData data = TransportContext.readRequest(in);
//			Object[] obj = (Object[]) data.request;
//			
//			if (path.startsWith(TransportRequest.STREAM)) {
//				handleContentStream(peer, in, out);
//			} else if (path.startsWith(TransportRequest.DOWNLOAD)) {
//				handleDownload(peer, in, out);
//			}

		} catch (Exception e) {
			e.printStackTrace();
			
			TransportContext.sendErrorResponse(out, e);
		}
	}

	private void handleDownload(String peer, ObjectInputStream in,
			ObjectOutputStream out) throws Exception {
		TransportData data = TransportContext.readRequest(in);
		Object[] obj = (Object[]) data.request;
		final Uri uri = Uri.parse((String)obj[0]);

		if (Debug.DEBUG) {
			Log.d(TAG, "handleDownload uri: " + uri );
		}
		
		final String scheme = uri.getScheme();
		File file = null;
		if (scheme.equals("file")) {
			file = new File(uri.toString());
		} else if (scheme.equals("content")){
			ContentResolver cr = ctx.getContentResolver();
			file = new File(getDataPath(cr, uri));
		}
		
		FileWrap wrap = new FileWrap(file);
		
		if (Debug.DEBUG) {
			Log.d(TAG, "handleDownload uri: " + uri  + " file wrap: " + wrap);
		}
		
		TransportContext.sendResponse(out, "", wrap);
	}

	private void handleContentStream(String peer, ObjectInputStream in,
			ObjectOutputStream out) throws Exception {
		
//		final Uri uri = Uri.parse((String)obj[0]);
//		final String mode = (String)obj[1];
//		
//		if (Debug.DEBUG) {
//			Log.d(TAG, "handleContentStream uri: " + uri + " mode: " +mode);
//		}
//		
//		final String scheme = uri.getScheme();
//		File file = null;
//		if (scheme.equals("file")) {
//			file = new File(uri.toString());
//		} else if (scheme.equals("content")){
//			ContentResolver cr = ctx.getContentResolver();
//			file = new File(getDataPath(cr, uri));
//		} else {
//			//TODO http etc 
//			TransportContext.sendErrorResponse(out, "Not supported: " + uri);
//			return;
//		}
//		
//		//check permission
//		if (mode.equals("r") && !file.canRead() 
//				|| mode.startsWith("rw") && !file.canWrite()) {
//			TransportContext.sendErrorResponse(out, "No permission: " + file + " mode: " + mode);
//		}
//		
//		TransportContext.sendResponse(out, "", "");
//		
//		//"r" "w", "wa", "rw", "rwt"
//		if (mode.equals("r")) {
//			FileInputStream fin = new FileInputStream(file);
//			startStreaming(fin, out);
//		} else if (mode.equals("w") || mode.equals("wa") || mode.equals("rw")) {
//			FileOutputStream fout = new FileOutputStream(file, true);
//			startStreaming(in, fout);
//		} else if (mode.equals("rwt")) {
//			FileOutputStream fout = new FileOutputStream(file, false);
//			startStreaming(in, fout);
//		}
	}
	
	private void startStreaming(InputStream in, OutputStream out) {
		CopyThread t1 = new CopyThread(in, out);
		pool.execute(t1);
	}

	public static String getDataPath(ContentResolver cr, Uri uri) {
		Cursor c = cr.query(uri, new String[] { "_data" }, null, null, null);
		c.moveToFirst();
		String p = c.getString(0);
		c.close();
		return p;
	}

	public static FileWrap download(String host, int port, Uri uri) throws Exception {
		if (Debug.DEBUG) {
			Log.d(TAG, "download host: " + host + " port: " + port + " uri: " + uri);
		}
		
		final Object[] data = new Object[] { uri.toString() };

		TransportRequest req = new TransportRequest();
		req.host = host;
		req.port = port;
		req.action = TransportRequest.DOWNLOAD;
		req.data = data;

		TransportResponse resp = new TransportResponse();

		TransportContext.handle(req, resp);

		if (Debug.DEBUG) {
			Log.d(TAG, "download host: " + host + " port: " + port + " uri: " + uri + " response: " + resp);
		}
		
		
		if (resp.code == TransportResponse.OK) {
			return (FileWrap) resp.data;
		}
		
		throw new IOException(resp.code + " " + resp.message);
	}
}
